Overall Objective

Load Libraries

library(tidyverse)
library(cowplot)
library(broom)
library(plotly)

Import data

Convert data from ‘wide’ to ‘long’ format

# data
data1 <- data %>%
  gather(Sample,Count,2:49)
# Separate samples by identifiers 
data2 <- data1 %>% 
  separate(Sample, into=c("Sample_ID","Dilution_factor",
                          "Injection","Tech_rep", sep = "_")) %>% 
  select(-`_`)
# Standards
standards1 <- standards %>% 
  gather(Sample,Count,2:25)
standards2 <- standards1 %>% 
  separate(Sample, into=c("Sample_ID","When","Dilution_factor",
                          "Nano_day","Injection","Tech_Rep", sep = "_")) %>% 
  select(-`_`)

Factor the data into categorical variables

# Refactoring Columns for samples
data2$Sample_ID <- as.factor(data2$Sample_ID)
data2$Dilution_factor <- as.numeric(data2$Dilution_factor)
data2$Injection<- as.factor(data2$Injection)
data2$Tech_rep <- as.numeric(data2$Tech_rep)
data2
# Refactoring COlumns for key
key$Sample_ID <- as.factor(key$Sample_ID)
key$Time <- as.factor(key$Time)
key$Treatment <- as.factor(key$Treatment)
key$Volume <- as.numeric(key$Volume)
key$Treatment <- factor(key$Treatment,levels = c('DMSO','EGF','BPS','BPS_EGF'))
key
# Refactoring columns for standards
standards2$Sample_ID <- as.factor(standards2$Sample_ID)
standards2$When <- as.factor(standards2$When)
standards2$Dilution_factor <- as.numeric(standards2$Dilution_factor)
standards2$Injection <- as.factor(standards2$Injection)
standards2$Nano_day <- as.numeric(standards2$Nano_day)
standards2

Back calculate standards

standards2 <- standards2 %>% 
  mutate(True_Count=Dilution_factor*Count)
# Set the correct order of 'categorical factors'
standards2$Nano_day <-  factor(standards2$Nano_day, levels=c('1','2'))
standards2$When <- factor(standards2$When, levels=c('before','after'))
standards2

Summarize three technical standard replicates

standards3 <- standards2 %>% 
  group_by(particle_size,Sample_ID,When,Dilution_factor,Nano_day,Injection) %>% 
  summarise( tech_N = length(True_Count),
             tech_mean = mean(True_Count),
             tech_sd = sd(True_Count),
             tech_se = tech_sd/sqrt(tech_N))
standards3

Summarize standards by injection

standards4 <- standards3 %>% 
  group_by(Nano_day,When,particle_size) %>% 
  summarise( inj_N = length(tech_mean),
             inj_mean = mean(tech_mean),
             inj_sd = sd(tech_mean),
             inj_se = inj_sd/sqrt(inj_N))
standards4

Plot before and after plots, facet by experimental day

std_plot <- standards4 %>% 
  ggplot(aes(x = particle_size, y = inj_mean, color=When))+
  geom_line(size=2) + xlim(0,300)+ #line size, x-axis scale
  geom_ribbon(aes(ymin=inj_mean-inj_se, ymax=inj_mean+inj_se),
              alpha=0.4,fill = alpha('grey12', 0.2)) + #error bars
  scale_y_continuous(expand=c(0,0))+ #set bottom of graph
  xlab("Particle Size") + # X axis label
  ylab("\nMean Particle Concentration/ml\n") + # Y axis label
  ggtitle("Nanosight Histogram of\n100nm Standards")+ #title
  labs(color="Condition")+ #Label table title
  facet_wrap(~ Nano_day)
std_plot
ggsave("Standards_histogram_plot.png",
       height = 5, width = 7, dpi = 300, units= "in")

Standards particle concentrations from each experimental day

standards_df <- standards4 %>% 
  group_by(Nano_day,When) %>% 
  summarise(total=sum(inj_mean))
standards_df

Bar graph of standards particle concentrations

standards_bar <- standards_df %>% 
  ggplot(aes(x=Nano_day,y=total,fill=When))+
  geom_col(position="dodge")+
  scale_y_continuous(expand=c(0,0))+ #set bottom of graph
  xlab("Experimental Day") + # X axis label
  ylab("\nMean Particle Concentration/ml\n") + # Y axis label
  ggtitle("Nanosight Histogram of\n100nm Standards")+ #title
  labs(color="When") #Label table title
standards_bar
ggsave("Standards_bar_plot.png",
       height = 5, width = 7, dpi = 300, units= "in")

Intraassay variability

Intra.assay_cv <- standards_df %>% 
  group_by(Nano_day) %>% 
  summarise(Intra_Day_N = length(total),
            Intra_Day_mean = mean(total),
            Intra_Day_sd = sd(total),
            Intra_Day_se = Intra_Day_sd/sqrt(Intra_Day_N),
            Intra_Day_cv = Intra_Day_sd/Intra_Day_mean )
Intra.assay_cv
# # Save as .csv
# write_csv(Intra.assay_cv,"Intra.assay_cv.csv")

Interassay variability

Inter.assay_cv <- Intra.assay_cv %>% 
  summarise(Inter_Day_N = length(Intra_Day_mean),
            Inter_Day_mean = mean(Intra_Day_mean),
            Inter_Day_sd = sd(Intra_Day_mean),
            Inter_Day_se = Inter_Day_sd/sqrt(Inter_Day_N),
            Inter_Day_cv = Inter_Day_sd/Inter_Day_mean )
Inter.assay_cv
# # Save as .csv
# write_csv(Inter.assay_cv,"Inter.assay_cv.csv")

Sample analysis

Back calculate the original concentration of the sample

data2 <- data2 %>% 
  mutate(True_Count = Dilution_factor*Count)
data2

Average three technical readings

data3 <- data2 %>% 
  group_by(particle_size,Sample_ID,Dilution_factor,Injection) %>% 
  summarise( tech_N = length(True_Count),
             tech_mean = mean(True_Count),
             tech_sd = sd(True_Count),
             tech_se = tech_sd/sqrt(tech_N))
data3

Summarize samples by injection (average both injections)

data4 <- data3 %>% 
  group_by(particle_size,Sample_ID,Dilution_factor) %>% 
  summarise( inj_N = length(tech_mean),
             inj_mean = mean(tech_mean),
             inj_sd = sd(tech_mean),
             inj_se = inj_sd/sqrt(inj_N))
data4
# Average technical replicates and merge with key
merge <- left_join(key,data3, by= "Sample_ID")
merge
# Save as .csv
# write_csv(merge,"Technical_replicate_average.csv")
 
# Average injection replicates and merge with key
merge1 <- left_join(key,data4, by= "Sample_ID")
merge1
# #Save as .csv
# write_csv(merge1,"Injection_replicate_average.csv")

Quick visualizations

Graphing all samples

sample_plot <- merge %>%
  ggplot(aes(x=particle_size, y=tech_mean,color=Injection ))+ #plot
  geom_ribbon(aes(ymin=tech_mean-tech_se,
                  ymax=tech_mean+tech_se),
                  alpha=0.2,fill = alpha('grey12', 0.2)) + #error bars
  geom_line(size=2.0, alpha = 0.8) + xlim(0,500)+ #line size, x-axis scale
  scale_y_continuous(expand=c(0,0))+ #set bottom of graph
  xlab("Particle Size") + # X axis label
  ylab("\nMean Particle Concentration/ml\n") + # Y axis label
  ggtitle("Nanosight Histogram of\nhCTBS treated with BPS")+ #title
  labs(color="Injection")+ #Label table title
  facet_grid(Time ~ Treatment)
  # geom_vline(xintercept = 200)+
  # annotate("text", x= 350, y = 1E8, label= "200nm")
sample_plot

# ggsave("Nanosight_Sample_Histogram.png", plot = sample_plot,
#        height = 10, width = 14, dpi = 200, units= "in")

Interactive Plot

ggplotly(sample_plot)

Particle concentration values for each of the samples

merge2 <- merge1 %>% 
  group_by(Time, Treatment, Volume) %>% 
  summarise(particle_conc=sum(inj_mean))
merge2

Correct for resuspension volume

merge3 <- merge2 %>% 
  mutate(particle_count = (Volume/1000)*particle_conc, # Create new column with number of particles
         corrected_particle_conc = (particle_conc/1E9)) # Create new column with correct particle concentration
merge3
# Save as .csv
write_csv(merge3,"Adjusted_particle_concentration.csv")

Barplot

plot1 <- merge3 %>% 
  ggplot(aes(x = Treatment, y = corrected_particle_conc, fill = Treatment)) +
  geom_bar(aes(text = paste("Particle Concentration:",
                            corrected_particle_conc)),
           stat="identity", position = "dodge")+
  xlab("\nTreatment\n") + # X axis label
  ylab("\nMean Vessicle Concentration\n(10^9 particles/ ml)\n") + # Y axis label
  ggtitle("Effect of BPS on Extracellular Vessicle\nRelease of hCTBs\n")+
  scale_y_continuous(breaks = seq(0,14,2),
                     limits = c(0,14),
                     expand = c(0,0))+ # set bottom of graph
  labs(color="Condition")+ # Label table title
  facet_wrap(~Time)
Ignoring unknown aesthetics: text
  
plot1
 ggsave("BPS_treated_hCTBs_48_96_facet_plot.png",
       height = 8, width = 10, dpi = 600, units= "in")

Interactive Plot

ggplotly(plot1)

Barplot

plot2 <- merge3 %>%
  group_by(Time) %>% 
  ggplot(aes(x = Treatment, y = corrected_particle_conc, fill = Time )) +
  geom_bar(position = "dodge", stat = "identity")+
  xlab("\nTreatment\n") + # X axis label
  ylab("\nMean Vessicle Concentration\n(10^9 particles/ ml)\n") + # Y axis label
  ggtitle("Effect of BPS on Extracellular Vessicle\nRelease of hCTBs\n")+
  scale_y_continuous(breaks = seq(0,14,2),
                     limits = c(0,14),
                     expand = c(0,0))+ # set bottom of graph
  labs(fill= "Time (hr)")
plot2
 ggsave("BPS_treated_hCTBs_48_96_plot.png",
       height = 5, width = 7, dpi = 600, units= "in")

Interactive Plot

ggplotly(plot2)

Statistics

fit <- aov(corrected_particle_conc ~ Time * Treatment ,data=merge3)
tidy(fit)
LS0tCnRpdGxlOiAiSHVtYW4gQ1RCIEJQUyBQcm9qZWN0IgphdXRob3I6ICJTZWFuIE5ndXllbiIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6IGRlZmF1bHQKICBodG1sX25vdGVib29rOiBkZWZhdWx0CiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0Ci0tLQojT3ZlcmFsbCBPYmplY3RpdmUgCgoKIyNMb2FkIExpYnJhcmllcwoKYGBge3IsIGVjaG89VFJVRSwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoY293cGxvdCkKbGlicmFyeShicm9vbSkKbGlicmFyeShwbG90bHkpCmBgYAoKIyNJbXBvcnQgZGF0YQpgYGB7ciwgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KI3NldHdkKCJ+L0dpdEh1Yi9FeHBlcmltZW50cy9DVEJfQlBTL2RhdGEvIikKc2V0d2QoIn4vTGlicmFyeS9Nb2JpbGUgRG9jdW1lbnRzL2NvbX5hcHBsZX5DbG91ZERvY3MvRXhwZXJpbWVudHMvQ1RCX0JQUy9kYXRhLyIpCgoKcmF3X2RhdGEgPC0gIkNUQl9waWxvdF80OGhyXzk2aHItRXhwZXJpbWVudFN1bW1hcnkuY3N2IgprZXlfZGF0YSA8LSAiS2V5X2hDVEJQZXRyb2ZmX0xvcGV6LmNzdiIKc3RhbmRhcmRfZGF0YSA8LSAic3RkX0NUQl9waWxvdF80OGhyXzk2aHItRXhwZXJpbWVudFN1bW1hcnkuY3N2IgoKCmRhdGEgPC0gcmVhZF9jc3YocmF3X2RhdGEpCnN0YW5kYXJkcyA8LSByZWFkX2NzdihzdGFuZGFyZF9kYXRhKQprZXkgPC0gcmVhZF9jc3Yoa2V5X2RhdGEpCgpkYXRhCnN0YW5kYXJkcwprZXkKYGBgCgojI0NvbnZlcnQgZGF0YSBmcm9tICd3aWRlJyB0byAnbG9uZycgZm9ybWF0CmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojIGRhdGEKZGF0YTEgPC0gZGF0YSAlPiUKICBnYXRoZXIoU2FtcGxlLENvdW50LDI6NDkpCgojIFNlcGFyYXRlIHNhbXBsZXMgYnkgaWRlbnRpZmllcnMgCmRhdGEyIDwtIGRhdGExICU+JSAKICBzZXBhcmF0ZShTYW1wbGUsIGludG89YygiU2FtcGxlX0lEIiwiRGlsdXRpb25fZmFjdG9yIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAiSW5qZWN0aW9uIiwiVGVjaF9yZXAiLCBzZXAgPSAiXyIpKSAlPiUgCiAgc2VsZWN0KC1gX2ApCgojIFN0YW5kYXJkcwpzdGFuZGFyZHMxIDwtIHN0YW5kYXJkcyAlPiUgCiAgZ2F0aGVyKFNhbXBsZSxDb3VudCwyOjI1KQoKCnN0YW5kYXJkczIgPC0gc3RhbmRhcmRzMSAlPiUgCiAgc2VwYXJhdGUoU2FtcGxlLCBpbnRvPWMoIlNhbXBsZV9JRCIsIldoZW4iLCJEaWx1dGlvbl9mYWN0b3IiLAogICAgICAgICAgICAgICAgICAgICAgICAgICJOYW5vX2RheSIsIkluamVjdGlvbiIsIlRlY2hfUmVwIiwgc2VwID0gIl8iKSkgJT4lIAogIHNlbGVjdCgtYF9gKQoKCmBgYAoKCiMjRmFjdG9yIHRoZSBkYXRhIGludG8gY2F0ZWdvcmljYWwgdmFyaWFibGVzCmBgYHtyLCB3YXJuaW5nPUZBTFNFfQojIFJlZmFjdG9yaW5nIENvbHVtbnMgZm9yIHNhbXBsZXMKZGF0YTIkU2FtcGxlX0lEIDwtIGFzLmZhY3RvcihkYXRhMiRTYW1wbGVfSUQpCmRhdGEyJERpbHV0aW9uX2ZhY3RvciA8LSBhcy5udW1lcmljKGRhdGEyJERpbHV0aW9uX2ZhY3RvcikKZGF0YTIkSW5qZWN0aW9uPC0gYXMuZmFjdG9yKGRhdGEyJEluamVjdGlvbikKZGF0YTIkVGVjaF9yZXAgPC0gYXMubnVtZXJpYyhkYXRhMiRUZWNoX3JlcCkKCmRhdGEyCgojIFJlZmFjdG9yaW5nIENPbHVtbnMgZm9yIGtleQprZXkkU2FtcGxlX0lEIDwtIGFzLmZhY3RvcihrZXkkU2FtcGxlX0lEKQprZXkkVGltZSA8LSBhcy5mYWN0b3Ioa2V5JFRpbWUpCmtleSRUcmVhdG1lbnQgPC0gYXMuZmFjdG9yKGtleSRUcmVhdG1lbnQpCmtleSRWb2x1bWUgPC0gYXMubnVtZXJpYyhrZXkkVm9sdW1lKQoKa2V5JFRyZWF0bWVudCA8LSBmYWN0b3Ioa2V5JFRyZWF0bWVudCxsZXZlbHMgPSBjKCdETVNPJywnRUdGJywnQlBTJywnQlBTX0VHRicpKQoKa2V5CgojIFJlZmFjdG9yaW5nIGNvbHVtbnMgZm9yIHN0YW5kYXJkcwpzdGFuZGFyZHMyJFNhbXBsZV9JRCA8LSBhcy5mYWN0b3Ioc3RhbmRhcmRzMiRTYW1wbGVfSUQpCnN0YW5kYXJkczIkV2hlbiA8LSBhcy5mYWN0b3Ioc3RhbmRhcmRzMiRXaGVuKQpzdGFuZGFyZHMyJERpbHV0aW9uX2ZhY3RvciA8LSBhcy5udW1lcmljKHN0YW5kYXJkczIkRGlsdXRpb25fZmFjdG9yKQpzdGFuZGFyZHMyJEluamVjdGlvbiA8LSBhcy5mYWN0b3Ioc3RhbmRhcmRzMiRJbmplY3Rpb24pCnN0YW5kYXJkczIkTmFub19kYXkgPC0gYXMubnVtZXJpYyhzdGFuZGFyZHMyJE5hbm9fZGF5KQoKc3RhbmRhcmRzMgoKYGBgCgoKCiMjI0JhY2sgY2FsY3VsYXRlIHN0YW5kYXJkcwpgYGB7cn0Kc3RhbmRhcmRzMiA8LSBzdGFuZGFyZHMyICU+JSAKICBtdXRhdGUoVHJ1ZV9Db3VudD1EaWx1dGlvbl9mYWN0b3IqQ291bnQpCgojIFNldCB0aGUgY29ycmVjdCBvcmRlciBvZiAnY2F0ZWdvcmljYWwgZmFjdG9ycycKc3RhbmRhcmRzMiROYW5vX2RheSA8LSAgZmFjdG9yKHN0YW5kYXJkczIkTmFub19kYXksIGxldmVscz1jKCcxJywnMicpKQpzdGFuZGFyZHMyJFdoZW4gPC0gZmFjdG9yKHN0YW5kYXJkczIkV2hlbiwgbGV2ZWxzPWMoJ2JlZm9yZScsJ2FmdGVyJykpCgpzdGFuZGFyZHMyCmBgYAoKIyMjU3VtbWFyaXplIHRocmVlIHRlY2huaWNhbCBzdGFuZGFyZCByZXBsaWNhdGVzCmBgYHtyfQpzdGFuZGFyZHMzIDwtIHN0YW5kYXJkczIgJT4lIAogIGdyb3VwX2J5KHBhcnRpY2xlX3NpemUsU2FtcGxlX0lELFdoZW4sRGlsdXRpb25fZmFjdG9yLE5hbm9fZGF5LEluamVjdGlvbikgJT4lIAogIHN1bW1hcmlzZSggdGVjaF9OID0gbGVuZ3RoKFRydWVfQ291bnQpLAogICAgICAgICAgICAgdGVjaF9tZWFuID0gbWVhbihUcnVlX0NvdW50KSwKICAgICAgICAgICAgIHRlY2hfc2QgPSBzZChUcnVlX0NvdW50KSwKICAgICAgICAgICAgIHRlY2hfc2UgPSB0ZWNoX3NkL3NxcnQodGVjaF9OKSkKc3RhbmRhcmRzMwpgYGAKCgojIyNTdW1tYXJpemUgc3RhbmRhcmRzIGJ5IGluamVjdGlvbgpgYGB7cn0Kc3RhbmRhcmRzNCA8LSBzdGFuZGFyZHMzICU+JSAKICBncm91cF9ieShOYW5vX2RheSxXaGVuLHBhcnRpY2xlX3NpemUpICU+JSAKICBzdW1tYXJpc2UoIGlual9OID0gbGVuZ3RoKHRlY2hfbWVhbiksCiAgICAgICAgICAgICBpbmpfbWVhbiA9IG1lYW4odGVjaF9tZWFuKSwKICAgICAgICAgICAgIGlual9zZCA9IHNkKHRlY2hfbWVhbiksCiAgICAgICAgICAgICBpbmpfc2UgPSBpbmpfc2Qvc3FydChpbmpfTikpCnN0YW5kYXJkczQKCmBgYAoKIyMjUGxvdCBiZWZvcmUgYW5kIGFmdGVyIHBsb3RzLCBmYWNldCBieSBleHBlcmltZW50YWwgZGF5CmBgYHtyfQpzdGRfcGxvdCA8LSBzdGFuZGFyZHM0ICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBwYXJ0aWNsZV9zaXplLCB5ID0gaW5qX21lYW4sIGNvbG9yPVdoZW4pKSsKICBnZW9tX2xpbmUoc2l6ZT0yKSArIHhsaW0oMCwzMDApKyAjbGluZSBzaXplLCB4LWF4aXMgc2NhbGUKICBnZW9tX3JpYmJvbihhZXMoeW1pbj1pbmpfbWVhbi1pbmpfc2UsIHltYXg9aW5qX21lYW4raW5qX3NlKSwKICAgICAgICAgICAgICBhbHBoYT0wLjQsZmlsbCA9IGFscGhhKCdncmV5MTInLCAwLjIpKSArICNlcnJvciBiYXJzCiAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZD1jKDAsMCkpKyAjc2V0IGJvdHRvbSBvZiBncmFwaAogIHhsYWIoIlBhcnRpY2xlIFNpemUiKSArICMgWCBheGlzIGxhYmVsCiAgeWxhYigiXG5NZWFuIFBhcnRpY2xlIENvbmNlbnRyYXRpb24vbWxcbiIpICsgIyBZIGF4aXMgbGFiZWwKICBnZ3RpdGxlKCJOYW5vc2lnaHQgSGlzdG9ncmFtIG9mXG4xMDBubSBTdGFuZGFyZHMiKSsgI3RpdGxlCiAgbGFicyhjb2xvcj0iQ29uZGl0aW9uIikrICNMYWJlbCB0YWJsZSB0aXRsZQogIGZhY2V0X3dyYXAofiBOYW5vX2RheSkKCnN0ZF9wbG90CgoKIyBnZ3NhdmUoIlN0YW5kYXJkc19oaXN0b2dyYW1fcGxvdC5wbmciLAojICAgICAgICBoZWlnaHQgPSA1LCB3aWR0aCA9IDcsIGRwaSA9IDMwMCwgdW5pdHM9ICJpbiIpCmBgYAoKIyMjIFN0YW5kYXJkcyBwYXJ0aWNsZSBjb25jZW50cmF0aW9ucyBmcm9tIGVhY2ggZXhwZXJpbWVudGFsIGRheQpgYGB7cn0Kc3RhbmRhcmRzX2RmIDwtIHN0YW5kYXJkczQgJT4lIAogIGdyb3VwX2J5KE5hbm9fZGF5LFdoZW4pICU+JSAKICBzdW1tYXJpc2UodG90YWw9c3VtKGlual9tZWFuKSkKCnN0YW5kYXJkc19kZgpgYGAKCiMjI0JhciBncmFwaCBvZiBzdGFuZGFyZHMgcGFydGljbGUgY29uY2VudHJhdGlvbnMKYGBge3J9CnN0YW5kYXJkc19iYXIgPC0gc3RhbmRhcmRzX2RmICU+JSAKICBnZ3Bsb3QoYWVzKHg9TmFub19kYXkseT10b3RhbCxmaWxsPVdoZW4pKSsKICBnZW9tX2NvbChwb3NpdGlvbj0iZG9kZ2UiKSsKICBzY2FsZV95X2NvbnRpbnVvdXMoZXhwYW5kPWMoMCwwKSkrICNzZXQgYm90dG9tIG9mIGdyYXBoCiAgeGxhYigiRXhwZXJpbWVudGFsIERheSIpICsgIyBYIGF4aXMgbGFiZWwKICB5bGFiKCJcbk1lYW4gUGFydGljbGUgQ29uY2VudHJhdGlvbi9tbFxuIikgKyAjIFkgYXhpcyBsYWJlbAogIGdndGl0bGUoIk5hbm9zaWdodCBIaXN0b2dyYW0gb2ZcbjEwMG5tIFN0YW5kYXJkcyIpKyAjdGl0bGUKICBsYWJzKGNvbG9yPSJXaGVuIikgI0xhYmVsIHRhYmxlIHRpdGxlCgpzdGFuZGFyZHNfYmFyCgojIGdnc2F2ZSgiU3RhbmRhcmRzX2Jhcl9wbG90LnBuZyIsCiMgICAgICAgIGhlaWdodCA9IDUsIHdpZHRoID0gNywgZHBpID0gMzAwLCB1bml0cz0gImluIikKYGBgCgojIyNJbnRyYWFzc2F5IHZhcmlhYmlsaXR5CmBgYHtyfQpJbnRyYS5hc3NheV9jdiA8LSBzdGFuZGFyZHNfZGYgJT4lIAogIGdyb3VwX2J5KE5hbm9fZGF5KSAlPiUgCiAgc3VtbWFyaXNlKEludHJhX0RheV9OID0gbGVuZ3RoKHRvdGFsKSwKICAgICAgICAgICAgSW50cmFfRGF5X21lYW4gPSBtZWFuKHRvdGFsKSwKICAgICAgICAgICAgSW50cmFfRGF5X3NkID0gc2QodG90YWwpLAogICAgICAgICAgICBJbnRyYV9EYXlfc2UgPSBJbnRyYV9EYXlfc2Qvc3FydChJbnRyYV9EYXlfTiksCiAgICAgICAgICAgIEludHJhX0RheV9jdiA9IEludHJhX0RheV9zZC9JbnRyYV9EYXlfbWVhbiApCkludHJhLmFzc2F5X2N2CgojICMgU2F2ZSBhcyAuY3N2CiMgd3JpdGVfY3N2KEludHJhLmFzc2F5X2N2LCJJbnRyYS5hc3NheV9jdi5jc3YiKQpgYGAKCiMjI0ludGVyYXNzYXkgdmFyaWFiaWxpdHkKYGBge3J9CkludGVyLmFzc2F5X2N2IDwtIEludHJhLmFzc2F5X2N2ICU+JSAKICBzdW1tYXJpc2UoSW50ZXJfRGF5X04gPSBsZW5ndGgoSW50cmFfRGF5X21lYW4pLAogICAgICAgICAgICBJbnRlcl9EYXlfbWVhbiA9IG1lYW4oSW50cmFfRGF5X21lYW4pLAogICAgICAgICAgICBJbnRlcl9EYXlfc2QgPSBzZChJbnRyYV9EYXlfbWVhbiksCiAgICAgICAgICAgIEludGVyX0RheV9zZSA9IEludGVyX0RheV9zZC9zcXJ0KEludGVyX0RheV9OKSwKICAgICAgICAgICAgSW50ZXJfRGF5X2N2ID0gSW50ZXJfRGF5X3NkL0ludGVyX0RheV9tZWFuICkKSW50ZXIuYXNzYXlfY3YKCiMgIyBTYXZlIGFzIC5jc3YKIyB3cml0ZV9jc3YoSW50ZXIuYXNzYXlfY3YsIkludGVyLmFzc2F5X2N2LmNzdiIpCmBgYAoKCgojU2FtcGxlIGFuYWx5c2lzCgojIyNCYWNrIGNhbGN1bGF0ZSB0aGUgb3JpZ2luYWwgY29uY2VudHJhdGlvbiBvZiB0aGUgc2FtcGxlCmBgYHtyfQpkYXRhMiA8LSBkYXRhMiAlPiUgCiAgbXV0YXRlKFRydWVfQ291bnQgPSBEaWx1dGlvbl9mYWN0b3IqQ291bnQpCmRhdGEyCmBgYAoKCiMjIyBBdmVyYWdlIHRocmVlIHRlY2huaWNhbCByZWFkaW5ncwpgYGB7cn0KZGF0YTMgPC0gZGF0YTIgJT4lIAogIGdyb3VwX2J5KHBhcnRpY2xlX3NpemUsU2FtcGxlX0lELERpbHV0aW9uX2ZhY3RvcixJbmplY3Rpb24pICU+JSAKICBzdW1tYXJpc2UoIHRlY2hfTiA9IGxlbmd0aChUcnVlX0NvdW50KSwKICAgICAgICAgICAgIHRlY2hfbWVhbiA9IG1lYW4oVHJ1ZV9Db3VudCksCiAgICAgICAgICAgICB0ZWNoX3NkID0gc2QoVHJ1ZV9Db3VudCksCiAgICAgICAgICAgICB0ZWNoX3NlID0gdGVjaF9zZC9zcXJ0KHRlY2hfTikpCmRhdGEzCmBgYAoKIyNTdW1tYXJpemUgc2FtcGxlcyBieSBpbmplY3Rpb24gKGF2ZXJhZ2UgYm90aCBpbmplY3Rpb25zKQpgYGB7ciwgd2FybmluZz1GQUxTRX0KCmRhdGE0IDwtIGRhdGEzICU+JSAKICBncm91cF9ieShwYXJ0aWNsZV9zaXplLFNhbXBsZV9JRCxEaWx1dGlvbl9mYWN0b3IpICU+JSAKICBzdW1tYXJpc2UoIGlual9OID0gbGVuZ3RoKHRlY2hfbWVhbiksCiAgICAgICAgICAgICBpbmpfbWVhbiA9IG1lYW4odGVjaF9tZWFuKSwKICAgICAgICAgICAgIGlual9zZCA9IHNkKHRlY2hfbWVhbiksCiAgICAgICAgICAgICBpbmpfc2UgPSBpbmpfc2Qvc3FydChpbmpfTikpCmRhdGE0CgojIEF2ZXJhZ2UgdGVjaG5pY2FsIHJlcGxpY2F0ZXMgYW5kIG1lcmdlIHdpdGgga2V5Cm1lcmdlIDwtIGxlZnRfam9pbihrZXksZGF0YTMsIGJ5PSAiU2FtcGxlX0lEIikKCm1lcmdlCgojIFNhdmUgYXMgLmNzdgojIHdyaXRlX2NzdihtZXJnZSwiVGVjaG5pY2FsX3JlcGxpY2F0ZV9hdmVyYWdlLmNzdiIpCiAKIyBBdmVyYWdlIGluamVjdGlvbiByZXBsaWNhdGVzIGFuZCBtZXJnZSB3aXRoIGtleQptZXJnZTEgPC0gbGVmdF9qb2luKGtleSxkYXRhNCwgYnk9ICJTYW1wbGVfSUQiKQoKbWVyZ2UxCgojICNTYXZlIGFzIC5jc3YKIyB3cml0ZV9jc3YobWVyZ2UxLCJJbmplY3Rpb25fcmVwbGljYXRlX2F2ZXJhZ2UuY3N2IikKCmBgYAoKCgojUXVpY2sgdmlzdWFsaXphdGlvbnMKCiMjIyBHcmFwaGluZyBhbGwgc2FtcGxlcwpgYGB7ciwgd2FybmluZz1GQUxTRX0Kc2FtcGxlX3Bsb3QgPC0gbWVyZ2UgJT4lCiAgZ2dwbG90KGFlcyh4PXBhcnRpY2xlX3NpemUsIHk9dGVjaF9tZWFuLGNvbG9yPUluamVjdGlvbiApKSsgI3Bsb3QKICBnZW9tX3JpYmJvbihhZXMoeW1pbj10ZWNoX21lYW4tdGVjaF9zZSwKICAgICAgICAgICAgICAgICAgeW1heD10ZWNoX21lYW4rdGVjaF9zZSksCiAgICAgICAgICAgICAgICAgIGFscGhhPTAuMixmaWxsID0gYWxwaGEoJ2dyZXkxMicsIDAuMikpICsgI2Vycm9yIGJhcnMKICBnZW9tX2xpbmUoc2l6ZT0yLjAsIGFscGhhID0gMC44KSArIHhsaW0oMCw1MDApKyAjbGluZSBzaXplLCB4LWF4aXMgc2NhbGUKICBzY2FsZV95X2NvbnRpbnVvdXMoZXhwYW5kPWMoMCwwKSkrICNzZXQgYm90dG9tIG9mIGdyYXBoCiAgeGxhYigiUGFydGljbGUgU2l6ZSIpICsgIyBYIGF4aXMgbGFiZWwKICB5bGFiKCJcbk1lYW4gUGFydGljbGUgQ29uY2VudHJhdGlvbi9tbFxuIikgKyAjIFkgYXhpcyBsYWJlbAogIGdndGl0bGUoIk5hbm9zaWdodCBIaXN0b2dyYW0gb2ZcbmhDVEJTIHRyZWF0ZWQgd2l0aCBCUFMiKSsgI3RpdGxlCiAgbGFicyhjb2xvcj0iSW5qZWN0aW9uIikrICNMYWJlbCB0YWJsZSB0aXRsZQogIGZhY2V0X2dyaWQoVGltZSB+IFRyZWF0bWVudCkKICAjIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDIwMCkrCiAgIyBhbm5vdGF0ZSgidGV4dCIsIHg9IDM1MCwgeSA9IDFFOCwgbGFiZWw9ICIyMDBubSIpCgpzYW1wbGVfcGxvdAoKIyBnZ3NhdmUoIk5hbm9zaWdodF9TYW1wbGVfSGlzdG9ncmFtLnBuZyIsIHBsb3QgPSBzYW1wbGVfcGxvdCwKIyAgICAgICAgaGVpZ2h0ID0gMTAsIHdpZHRoID0gMTQsIGRwaSA9IDIwMCwgdW5pdHM9ICJpbiIpCmBgYAojIyNJbnRlcmFjdGl2ZSBQbG90CmBgYHtyfQpnZ3Bsb3RseShzYW1wbGVfcGxvdCkKYGBgCgoKCiMjIyBQYXJ0aWNsZSBjb25jZW50cmF0aW9uIHZhbHVlcyBmb3IgZWFjaCBvZiB0aGUgc2FtcGxlcwpgYGB7cn0KbWVyZ2UyIDwtIG1lcmdlMSAlPiUgCiAgZ3JvdXBfYnkoVGltZSwgVHJlYXRtZW50LCBWb2x1bWUpICU+JSAKICBzdW1tYXJpc2UocGFydGljbGVfY29uYz1zdW0oaW5qX21lYW4pKQptZXJnZTIKYGBgCgojIyMgQ29ycmVjdCBmb3IgcmVzdXNwZW5zaW9uIHZvbHVtZQpgYGB7cn0KbWVyZ2UzIDwtIG1lcmdlMiAlPiUgCiAgbXV0YXRlKHBhcnRpY2xlX2NvdW50ID0gKFZvbHVtZS8xMDAwKSpwYXJ0aWNsZV9jb25jLCAjIENyZWF0ZSBuZXcgY29sdW1uIHdpdGggbnVtYmVyIG9mIHBhcnRpY2xlcwogICAgICAgICBjb3JyZWN0ZWRfcGFydGljbGVfY29uYyA9IChwYXJ0aWNsZV9jb25jLzFFOSkpICMgQ3JlYXRlIG5ldyBjb2x1bW4gd2l0aCBjb3JyZWN0IHBhcnRpY2xlIGNvbmNlbnRyYXRpb24KbWVyZ2UzCgojIFNhdmUgYXMgLmNzdgojIHdyaXRlX2NzdihtZXJnZTMsIkFkanVzdGVkX3BhcnRpY2xlX2NvbmNlbnRyYXRpb24uY3N2IikKCmBgYAoKCiMjI0JhcnBsb3QKYGBge3IsIHdhcm5pbmc9VFJVRX0KcGxvdDEgPC0gbWVyZ2UzICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBUcmVhdG1lbnQsIHkgPSBjb3JyZWN0ZWRfcGFydGljbGVfY29uYywgZmlsbCA9IFRyZWF0bWVudCkpICsKICBnZW9tX2JhcihhZXModGV4dCA9IHBhc3RlKCJQYXJ0aWNsZSBDb25jZW50cmF0aW9uOiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3JyZWN0ZWRfcGFydGljbGVfY29uYykpLAogICAgICAgICAgIHN0YXQ9ImlkZW50aXR5IiwgcG9zaXRpb24gPSAiZG9kZ2UiKSsKICB4bGFiKCJcblRyZWF0bWVudFxuIikgKyAjIFggYXhpcyBsYWJlbAogIHlsYWIoIlxuTWVhbiBWZXNzaWNsZSBDb25jZW50cmF0aW9uXG4oMTBeOSBwYXJ0aWNsZXMvIG1sKVxuIikgKyAjIFkgYXhpcyBsYWJlbAogIGdndGl0bGUoIkVmZmVjdCBvZiBCUFMgb24gRXh0cmFjZWxsdWxhciBWZXNzaWNsZVxuUmVsZWFzZSBvZiBoQ1RCc1xuIikrCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLDE0LDIpLAogICAgICAgICAgICAgICAgICAgICBsaW1pdHMgPSBjKDAsMTQpLAogICAgICAgICAgICAgICAgICAgICBleHBhbmQgPSBjKDAsMCkpKyAjIHNldCBib3R0b20gb2YgZ3JhcGgKICBsYWJzKGNvbG9yPSJDb25kaXRpb24iKSsgIyBMYWJlbCB0YWJsZSB0aXRsZQogIGZhY2V0X3dyYXAoflRpbWUpCgogIApwbG90MQoKIyBnZ3NhdmUoIkJQU190cmVhdGVkX2hDVEJzXzQ4Xzk2X2ZhY2V0X3Bsb3QucG5nIiwKIyAgICAgICBoZWlnaHQgPSA4LCB3aWR0aCA9IDEwLCBkcGkgPSA2MDAsIHVuaXRzPSAiaW4iKQpgYGAKIyNJbnRlcmFjdGl2ZSBQbG90CmBgYHtyfQpnZ3Bsb3RseShwbG90MSkKYGBgCgojIyNCYXJwbG90CmBgYHtyfQpwbG90MiA8LSBtZXJnZTMgJT4lCiAgZ3JvdXBfYnkoVGltZSkgJT4lIAogIGdncGxvdChhZXMoeCA9IFRyZWF0bWVudCwgeSA9IGNvcnJlY3RlZF9wYXJ0aWNsZV9jb25jLCBmaWxsID0gVGltZSApKSArCiAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZG9kZ2UiLCBzdGF0ID0gImlkZW50aXR5IikrCiAgeGxhYigiXG5UcmVhdG1lbnRcbiIpICsgIyBYIGF4aXMgbGFiZWwKICB5bGFiKCJcbk1lYW4gVmVzc2ljbGUgQ29uY2VudHJhdGlvblxuKDEwXjkgcGFydGljbGVzLyBtbClcbiIpICsgIyBZIGF4aXMgbGFiZWwKICBnZ3RpdGxlKCJFZmZlY3Qgb2YgQlBTIG9uIEV4dHJhY2VsbHVsYXIgVmVzc2ljbGVcblJlbGVhc2Ugb2YgaENUQnNcbiIpKwogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMCwxNCwyKSwKICAgICAgICAgICAgICAgICAgICAgbGltaXRzID0gYygwLDE0KSwKICAgICAgICAgICAgICAgICAgICAgZXhwYW5kID0gYygwLDApKSsgIyBzZXQgYm90dG9tIG9mIGdyYXBoCiAgbGFicyhmaWxsPSAiVGltZSAoaHIpIikKCnBsb3QyCgogIyBnZ3NhdmUoIkJQU190cmVhdGVkX2hDVEJzXzQ4Xzk2X3Bsb3QucG5nIiwKICMgICAgICAgaGVpZ2h0ID0gNSwgd2lkdGggPSA3LCBkcGkgPSA2MDAsIHVuaXRzPSAiaW4iKQpgYGAKIyMgSW50ZXJhY3RpdmUgUGxvdApgYGB7cn0KZ2dwbG90bHkocGxvdDIpCmBgYAoKCgojIFN0YXRpc3RpY3MKCmBgYHtyfQpmaXQgPC0gYW92KGNvcnJlY3RlZF9wYXJ0aWNsZV9jb25jIH4gVGltZSAqIFRyZWF0bWVudCAsZGF0YT1tZXJnZTMpCgp0aWR5KGZpdCkKYGBgCgo=